package com.tcm.user.persistence;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.base.core.codec.Md5Utils;
import com.base.core.exception.ServiceException;
import com.base.core.lang.StringUtils;
import com.base.core.utils.R;
import com.base.genid.generator.UidGenerator;
import com.tcm.user.dao.LoginAuthMapper;
import com.tcm.user.model.dto.LoginAuthDTO;
import com.tcm.user.model.query.LoginAuthQuery;
import com.tcm.user.model.entity.LoginAuth;
import com.tcm.user.constants.enums.BusinessCodeEnum;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class LoginAuthPersisServiceImpl implements LoginAuthPersisService {

    @Autowired
    private LoginAuthMapper loginMapper;

    @DubboReference(version = "0.0.1-beta", group = "cached-uid", check = false, retries = 3)
    private UidGenerator uidGenerator;


    @Override
    public Long save(LoginAuth login) throws ServiceException{

        try{
            //查询登录账号是否存在
            String password = login.getCredential();
            if(StringUtils.isNotBlank(password)){
                String salt = RandomUtil.randomNumbers(6);
                password = Md5Utils.md5((password + salt));
                login.setSalt(salt);
                login.setCredential(password);
            }
            //保存登录账号信息
            login.setId(uidGenerator.getUID());
            login.setUpdateTime(DateUtil.date());
            login.setLoginTime(DateUtil.date());
            login.setCreateTime(DateUtil.date());
            login.setDeleted(new Byte("0"));
            login.setStatus(new Byte("0"));
            loginMapper.insert(login);
            return login.getId();
        }catch (ServiceException e){
            R.throwFail(e.getResult().getCode(), e.getMessage());
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }
        return null;
    }

    @Override
    public int update(LoginAuth login) throws ServiceException{

        try{
            String password = login.getCredential();
            if(StringUtils.isNotBlank(password)){
                String salt = RandomUtil.randomNumbers(6);
                password = Md5Utils.md5((password + salt));
                login.setSalt(salt);
                login.setCredential(password);
            }
            login.setUpdateTime(DateUtil.date());
            return loginMapper.update(login);
        }catch (ServiceException e){
            R.throwFail(e.getResult().getCode(), e.getMessage());
        }catch (Exception e){
            R.throwFail(e.getMessage());
        }
        return 0;
    }

    /**
     * 获取单条数数据
     *
     * @param identifier   账号
     * @param clientType 客户端类型
     * @return
     */
    @Override
    public LoginAuth findByUsername(String identifier, String clientType) throws ServiceException{
        LoginAuth userLogin = null;
        try {
            userLogin = loginMapper.findByUsername(identifier, clientType);
        }catch (Exception e){
            R.throwFail(BusinessCodeEnum.FAILED_TO_QUERY_USER);
        }
        return userLogin;
    }

    /**
     * 获取单条数数据
     *
     * @param loginAuth
     * @return
     */
    @Override
    public R queryUser(LoginAuth loginAuth) throws ServiceException{
        LoginAuth userLogin;
        try {
            if(ObjectUtil.isNull(loginAuth.getId())){
                return R.fail(BusinessCodeEnum.USER_ID_NOT_FOUND);
            }
            if(StringUtils.isBlank(loginAuth.getClientType())){
                return R.fail(BusinessCodeEnum.USER_ID_NOT_FOUND);
            }
            userLogin = loginMapper.queryUser(loginAuth);
            return R.success(userLogin);
        }catch (Exception e){
            return R.fail(BusinessCodeEnum.FAILED_TO_QUERY_USER);
        }
    }

    /**
     * 获取单条数数据
     *
     * @param userId   用户id
     * @param clientType 客户端类型
     * @return
     */
    @Override
    public R findByUserId(Long userId, String clientType) throws ServiceException{
        LoginAuth userLogin = null;
        try {
            userLogin = loginMapper.findByUserId(userId, clientType);
        }catch (Exception e){
            return R.fail(BusinessCodeEnum.FAILED_TO_QUERY_USER);
        }
        return R.success(userLogin);
    }

    @Override
    public LoginAuth findByMobile(String mobile, String clientType) throws ServiceException{
        LoginAuth userLogin = null;
        try {
            userLogin = loginMapper.findByMobile(mobile, clientType);
        }catch (ServiceException e){
            R.throwFail(BusinessCodeEnum.FAILED_TO_QUERY_USER);
        }
        return userLogin;
    }

    @Override
    public List<LoginAuthDTO> queryByMobile(List<String> mobileList, String clientType) {
        List<LoginAuthDTO> loginAuthDTOS = null;
        try {
            if(mobileList == null){
                return null;
            }
            List<LoginAuth> loginAuthList = loginMapper.queryByMobile(mobileList, clientType);
            if(loginAuthList != null){
               loginAuthDTOS = loginAuthList.stream().map(loginAuth -> {
                   LoginAuthDTO loginAuthDTO = new LoginAuthDTO();
                   BeanUtils.copyProperties(loginAuth, loginAuthDTO);
                   return loginAuthDTO;
               }).collect(Collectors.toList());
            }
        }catch (ServiceException e){
            R.throwFail(BusinessCodeEnum.FAILED_TO_QUERY_USER);
        }
        return loginAuthDTOS;

    }


    @Override
    public R changeCredential(LoginAuthQuery loginAuthQuery) {
        try{
            String password = loginAuthQuery.getCredential();
            String clientType = loginAuthQuery.getClientType();
            Long userId = loginAuthQuery.getId();
            LoginAuth login = loginMapper.findByUserId(userId, clientType);
            if(ObjectUtil.isEmpty(login)){
                return R.fail(BusinessCodeEnum.USER_NOT_FOUND);
            }
            String salt = StringUtils.isNotEmpty(login.getSalt()) ? login.getSalt() : RandomUtil.randomNumbers(6);
            login.setCredential(Md5Utils.md5(password + salt));
            login.setClientType(clientType);
            loginMapper.changeCredential(login.getId(), login.getCredential(), login.getClientType());
        }catch (ServiceException | GeneralSecurityException e){
            return R.fail(e.getMessage());
        }
        return R.success();
    }

    @Override
    public R changeUsername(LoginAuthQuery loginAuthQuery) {
        try{
            loginMapper.updateUsername(loginAuthQuery.getId(), loginAuthQuery.getPrincipal(),
                    loginAuthQuery.getClientType());
        }catch (Exception e){
            return R.fail(e.getMessage());
        }
        return R.success();
    }

    @Override
    public R changeMobile(LoginAuthQuery userParams) {
        try {
            //修改手机号
            loginMapper.updateMobile(userParams.getId(),userParams.getPrincipal(), userParams.getClientType());
        }catch (Exception e){
            return R.fail(e.getMessage());
        }
        return R.success();
    }

    @Override
    public R checkUsernameExists(String username, Long userId, String clientType) {
        LoginAuth loginAuth = loginMapper.checkUsernameExists(userId, username, clientType);
        Map<String, Boolean> resultMap = new HashMap<>();
        resultMap.put("isUserExists", true);
        if(loginAuth == null){
            return R.success(false);
        }
        if(StringUtils.isBlank(loginAuth.getUsername())){
            return R.success(false);
        }
        return R.success(resultMap);
    }

    @Override
    public R checkMobileExists(String mobile, Long userId, String clientType) {
        LoginAuth loginAuth = loginMapper.checkMobileExists(userId, mobile, clientType);
        Map<String, Boolean> resultMap = new HashMap<>();
        resultMap.put("isMobileExists", true);
        if(loginAuth == null){
            return R.success(false);
        }
        if(StringUtils.isBlank(loginAuth.getMobile())){
            return R.success(false);
        }
        return R.success(resultMap);
    }

}
